package com.epam.training.concurrency.second.task4;

import java.math.BigInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 
 * Calculate series like 1, 2, 4, 8, 16, 32..
 * 
 * @author bogdan
 *
 */
public class Series {

	public final static String FIRST_SERIES_NUMBER = "1";

	/**
	 * Encapsulate current numeric value of series
	 * 
	 * @author bogdan
	 *
	 */
	private static class State {
		final BigInteger curr;

		public State(BigInteger curr) {
			this.curr = curr;
		}
	}

	private final AtomicReference<State> atomicState = new AtomicReference<State>(
			new State(new BigInteger(FIRST_SERIES_NUMBER)));

	/**
	 * Calculate next number of series
	 * 
	 * @return next number of series
	 */
	public BigInteger next() {
		BigInteger value = null;

		while (true) {
			State state = atomicState.get();
			value = state.curr;
			State newState = new State(state.curr.shiftLeft(1));

			if (atomicState.compareAndSet(state, newState)) {
				break;
			}
		}

		return value;
	}
}
